﻿using Fast;
using Fast.DynamicProxies;
using System;
using System.Linq;
using System.Reflection;

namespace Microsoft.Extensions.DependencyInjection
{
    /// <summary>
    /// 代理服务扩展类
    /// </summary>
    [SkipScan]
    public static class DispatchProxyServiceCollectionExtensions
    {
        /// <summary>
        /// 添加动态代理
        /// </summary>
        /// <param name="services"></param>
        public static IServiceCollection AddDynamicProxy(this IServiceCollection services)
        {
            //过滤定义了IntercepAttribute特性并且有接口的类
            var definedIntercepAttributeTypes = App.Types.Where(t => t.IsDefined(typeof(InterceptorAttribute), false) && t.GetInterfaces().Where(i => i.GetType() != typeof(IFastInterceptor)).Count() > 0);

            foreach (var definedIntercepAttributeType in definedIntercepAttributeTypes)
            {
                //获取接口
                var definedInterceptorInterfaceTypes = definedIntercepAttributeType.GetInterfaces();

                foreach (var definedInterceptorInterfaceType in definedInterceptorInterfaceTypes)
                {
                    //将目标类的接口注入DynamicProxy.Create<T>创建的代理类
                    services.AddTransient(definedInterceptorInterfaceType, sp =>
                    {
                        //获取创建代理类的方法
                        var dynamicProxyCreateMethod = typeof(DynamicProxy).GetMethod(nameof(DynamicProxy.Create));
                        //获取标记了IntercepAttribute特性的类
                        var target = ActivatorUtilities.CreateInstance(sp, definedIntercepAttributeType);
                        //获取拦截器
                        var interceptorAttribute = target.GetType().GetCustomAttribute<InterceptorAttribute>();
                        var targetInterceptorType = (IFastInterceptor)ActivatorUtilities.CreateInstance(sp, interceptorAttribute.InterceptorType);
                        Action<object[]> beforeAction = targetInterceptorType.BeforeAction;
                        Action<object[], object> afterAction = targetInterceptorType.AfterAction;
                        //执行上面获取的创建代理类的方法
                        dynamic proxy = dynamicProxyCreateMethod.MakeGenericMethod(definedInterceptorInterfaceType)
                                                            .Invoke(null, new object[] { target, beforeAction, afterAction });

                        return proxy;
                    });
                }
            }

            return services;
        }
    }
}
